// 什么是类型推论

/* 
1.我声明了一个变量但是没有定义类型

TypeScript 会在没有明确的指定类型的时候推测出一个类型，这就是类型推论
不能够在赋值给别的类型
*/

let typeInferenceStr = "小满zs"
// typeInferenceStr = 123 // 报错

/* 
2.如果你声明变量没有定义类型也没有赋值这时候TS会推断成any类型可以进行任何操作
*/
let typeInferenceNum01

/*
3.如果变量声明的时候没有赋值，但是定义了类型，那么TS会认为这个变量是这个类型的空值，也就是undefined
*/

let typeInferenceNum02: string

/* 
类型别名
type 关键字（可以给一个类型定义一个名字）多用于复合类型
*/

// 定义类型别名
type TypeInferenceNum03 = string | number
let TypeInference01: TypeInferenceNum03 = "123"
console.log(TypeInference01)

// 定义函数别名
type TypeInferenceFn = () => string
let TypeInferenceFn01: TypeInferenceFn = () => "123"

//  定义联合类型别名
type strTypeInference = string | number
let s1: strTypeInference = 123
let s2: strTypeInference = '123'

console.log(s1, s2);

// 定义值的别名
type value = boolean | 0 | '213'
let s3: value = true
//变量s3的值  只能是上面value定义的值

/* 
type 和 interface 还是一些区别的 虽然都可以定义类型

1.interface可以继承  type 只能通过 & 交叉类型合并
2.type 可以定义 联合类型 和 可以使用一些操作符 interface不行
3.interface 遇到重名的会合并 type 不行 
*/


/* 
type高级用法

左边的值会作为右边值的子类型遵循图中上下的包含关系

类型层级
1.any unknow
2.Object
3.Number
4.number
5.never
*/

// extends包含的意思
// 左边的值 会作为右边类型的子类型
type numTypeInference01 = 1 extends number ? 1 : 0 // 1
type numTypeInference02 = 1 extends Number ? 1 : 0 // 1
type numTypeInference03 = 1 extends Object ? 1 : 0 // 1
type numTypeInference04 = 1 extends any ? 1 : 0 // 1
// type numTypeInference05 = 1 extends unknow ? 1 : 0 // 1
type numTypeInference06 = 1 extends never ? 1 : 0 // 0